package com.imooc.service.impl;

import com.imooc.dao.ProductInfoMapper;
import com.imooc.dataobject.OrderDetail;
import com.imooc.dataobject.OrderMaster;
import com.imooc.dataobject.ProductInfo;
import com.imooc.dto.OrderDTO;
import com.imooc.enums.OrderStatusEnum;
import com.imooc.enums.PayStatusEnum;
import com.imooc.enums.ResultEnum;
import com.imooc.exception.SellException;
import com.imooc.redis.OrderKey;
import com.imooc.redis.ProductKey;
import com.imooc.redis.RedisService;
import com.imooc.repository.OrderDetailRepository;
import com.imooc.repository.OrderMasterRepository;
import com.imooc.service.*;
import com.imooc.utils.JsonUtil;
import com.imooc.utils.KeyUtil;
import com.imooc.utils.MsgProducer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Created by MisterDeng on 2018/5/10/010 11:51.
 */
@Service
@Slf4j
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private RedisService redisService;

    @Autowired
    private OrderService orderService;
    @Autowired
    private ProductService productService;

    @Autowired
    private OrderDetailRepository orderDetailRepository;

    @Autowired
    private OrderMasterRepository orderMasterRepository;

    @Autowired
    private ProductInfoMapper productInfoMapper;

    @Autowired
    private PayService payService;

    @Autowired
    private PushMessageService pushMessageService;

    @Autowired
    private WebSocket webSocket;

    @Autowired
    private MsgProducer producer;

    /**
     * 秒杀下单.
     *
     * @param orderDTO
     */
    @Override
    @Transactional
    public OrderDTO seckill(OrderDTO orderDTO) {
        // 计算总价
        String orderId = KeyUtil.genUniqueKey();
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);

        //1. 查询商品（数量, 价格）
        for (OrderDetail orderDetail : orderDTO.getOrderDetailList()) {
            // 查询库存
            ProductInfo product = redisService.get(ProductKey.product, orderDetail.getProductId(), ProductInfo.class);

            if (product == null) {
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }

            long stock = redisService.decrBy(ProductKey.stock, orderDetail.getProductId(), orderDetail.getProductQuantity());
            if (stock<0) {
                redisService.incrBy(ProductKey.stock, orderDetail.getProductId(), orderDetail.getProductQuantity());
                // 该商品库存不足
                throw new RuntimeException("商品库存不足");
            }


            // 计算订单总价
            orderAmount = product.getProductPrice()
                    .multiply(new BigDecimal(orderDetail.getProductQuantity()))
                    .add(orderAmount);

            //订单详情入库 (此处用队列)
            orderDetail.setDetailId(KeyUtil.genUniqueKey());
            orderDetail.setOrderId(orderId);
            BeanUtils.copyProperties(product, orderDetail);
            orderDetail.setProductStock(Math.toIntExact(stock));
            // 发送消息
            producer.sendMessage("topic-order", redisService.beanToString(orderDetail));
        }


        //3. 写入订单数据库（orderMaster和orderDetail）
        OrderMaster orderMaster = new OrderMaster();
        orderDTO.setOrderId(orderId);
        BeanUtils.copyProperties(orderDTO, orderMaster);
        orderMaster.setOrderAmount(orderAmount);
        orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
        orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode());
        orderMasterRepository.save(orderMaster);

        return orderDTO;

    }

    @Override
    public void saveOrderDetail(String content) {
        orderDetailRepository.save(redisService.stringToBean(content, OrderDetail.class));
    }

}
